
package com.quartet.exception.handler;

import com.google.common.collect.Lists;
import com.quartet.api.ApiResult;
import com.quartet.api.MapServerException;
import com.quartet.api.ResultErrorEnum;
import com.quartet.utils.StringUtils;
import com.quartet.utils.ThrowableUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.MessageSource;
import org.springframework.http.HttpStatus;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

/**
 * @author Zheng Jie
 * @date 2018-11-23
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionHandler {

    @Autowired
    private LocaleMessage localeMessage;

    /**
     * 处理所有不可知的异常
     */
    @ExceptionHandler(Throwable.class)
    public ApiResult handleException(Throwable e) {
        // 打印堆栈信息
        log.error(ThrowableUtil.getStackTrace(e));
//        return buildResponseEntity(ApiError.error(e.getMessage()));
        String message = localeMessage.getMessage(ResultErrorEnum.SYSTEM_INTERNAL_EXCEPTION.getCode());
        if (StringUtils.isNotBlank(message)) {
            return ApiResult.failed(ResultErrorEnum.SYSTEM_INTERNAL_EXCEPTION.getCode(), message, null);
        } else {
            return ApiResult.failed(ResultErrorEnum.SYSTEM_INTERNAL_EXCEPTION.getCode(), ResultErrorEnum.SYSTEM_INTERNAL_EXCEPTION.getMsg(), null);
        }
    }

    /**
     * BadCredentialsException
     */
    @ExceptionHandler(BadCredentialsException.class)
    public ApiResult badCredentialsException(BadCredentialsException e) {
        log.error("error info is:{}",e);
//        // 打印堆栈信息
//        String message = "坏的凭证".equals(e.getMessage()) ? "用户名或密码不正确" : e.getMessage();

        String message = localeMessage.getMessage(ResultErrorEnum.BMKPT004.getCode());
        if (StringUtils.isNotBlank(message)) {
            return ApiResult.failed(ResultErrorEnum.BMKPT004.getCode(), message, null);
        } else {
            return ApiResult.failed(ResultErrorEnum.BMKPT004.getCode(), ResultErrorEnum.BMKPT004.getMsg(), null);
        }
    }

    /**
     * 处理自定义异常
     */
//    @ExceptionHandler(value = BadRequestException.class)
//    public ApiResult badRequestException(BadRequestException e) {
//        // 打印堆栈信息
//        log.error(ThrowableUtil.getStackTrace(e));
//        return buildResponseEntity(ApiError.error(e.getStatus(), e.getMessage()));
//    }

    /**
     * 处理 EntityExist
     */
//    @ExceptionHandler(value = EntityExistException.class)
//    public ApiResult entityExistException(EntityExistException e) {
//        // 打印堆栈信息
//        log.error(ThrowableUtil.getStackTrace(e));
//        return buildResponseEntity(ApiError.error(e.getMessage()));
//    }

    /**
     * 处理 EntityNotFound
     */
//    @ExceptionHandler(value = EntityNotFoundException.class)
//    public ApiResult entityNotFoundException(EntityNotFoundException e) {
//        // 打印堆栈信息
//        log.error(ThrowableUtil.getStackTrace(e));
//        return buildResponseEntity(ApiError.error(NOT_FOUND.value(), e.getMessage()));
//    }

    /**
     * 处理所有接口数据验证异常
     */
//    @ExceptionHandler(MethodArgumentNotValidException.class)
//    public ApiResult handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
//        // 打印堆栈信息
//        log.error(ThrowableUtil.getStackTrace(e));
//        String[] str = Objects.requireNonNull(e.getBindingResult().getAllErrors().get(0).getCodes())[1].split("\\.");
//        String message = e.getBindingResult().getAllErrors().get(0).getDefaultMessage();
//        String msg = "不能为空";
//        if (msg.equals(message)) {
//            message = str[1] + ":" + message;
//        }
//        return buildResponseEntity(ApiError.error(message));
//    }

    /**
     * 处理自定义业务异常
     *
     * @param req
     * @param e
     * @return
     */
    @ExceptionHandler(value = MapServerException.class)
    @ResponseStatus(HttpStatus.OK)
    public ApiResult handleProductException(HttpServletRequest req, MapServerException e) {
        log.error("MapServerException:{}-{}", e.getErrorCode(), e.getResultErrorEnum().getMsg());
        String message = localeMessage.getMessage(e.getErrorCode());
        if (StringUtils.isNotBlank(message)) {
            return ApiResult.failed(e.getErrorCode(), message, null);
        } else {
            return ApiResult.failed(e.getErrorCode(), e.getResultErrorEnum().getMsg(), null);
        }

    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    @ResponseStatus(HttpStatus.OK)
    public ApiResult handleMethodArgumentNotValidException(MethodArgumentNotValidException e) {
        List<FieldError> fieldErrors = e.getBindingResult().getFieldErrors();
        List<String> errors = Lists.newArrayList();
        for (FieldError error : fieldErrors) {
            errors.add(localeMessage.getMessage(error.getDefaultMessage()));
        }
        return ApiResult.failed(ResultErrorEnum.BMKPCM00.getCode(), StringUtils.join(errors, " | "), null);
    }

    /**
     * 统一返回
     */
    private ApiResult buildResponseEntity(ApiError apiError) {
//        return new ResponseEntity<>(apiError, HttpStatus.valueOf(apiError.getStatus()));
        return ApiResult.failed(apiError.getStatus().toString(), apiError.getMessage(), null);
    }
}
